﻿using FreeSql.DataAnnotations;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;


namespace ZoneLineNew.Models.Entity.Base {
    /// <summary>
    /// 添加接口
    /// </summary>
    /// <typeparam name="TKey"></typeparam>
    public interface IEntityAdd<TKey> where TKey : struct {

    }

    /// <summary>
    /// 删除接口
    /// </summary>
    public interface IDelete {

    }

    /// <summary>
    /// 修改接口
    /// </summary>
    /// <typeparam name="TKey"></typeparam>
    public interface IEntityUpdate<TKey> where TKey : struct {
        
    }



    public interface IEntity<TKey> {
        /// <summary>
        /// 主键Id
        /// </summary>
        TKey Id { get; set; }
    }

    public interface IEntity : IEntity<long> {
    }

    public class Entity<TKey> : IEntity<TKey> {
        /// <summary>
        /// 主键Id
        /// </summary>
        [Description("主键Id")]
        [Column(Position = 1, IsIdentity = true, IsPrimary = true)]
        [JsonProperty(Order = -30)]
        public virtual TKey Id { get; set; }
    }

    public class Entity : Entity<long> {
    }

    /// <summary>
    /// 实体创建
    /// </summary>
    public class EntityAdd<TKey> : Entity<TKey>, IEntityAdd<TKey> where TKey : struct {
        
    }

    /// <summary>
    /// 实体创建
    /// </summary>
    public class EntityAdd : EntityAdd<long> {
    }

    /// <summary>
    /// 实体修改
    /// </summary>
    public class EntityUpdate<TKey> : EntityAdd<TKey>, IEntityUpdate<TKey> where TKey : struct {
        
    }

    /// <summary>
    /// 实体修改
    /// </summary>
    public class EntityUpdate : EntityUpdate<long> {
    }

    /// <summary>
    /// 实体删除
    /// </summary>
    public class EntityDelete<TKey> : EntityUpdate<TKey>, IDelete where TKey : struct {
       
    }

    /// <summary>
    /// 实体删除
    /// </summary>
    public class EntityDelete : EntityDelete<long> {

    }

    /// <summary>
    /// 实体基类
    /// </summary>
    public class EntityBase<TKey> : EntityDelete<TKey> where TKey : struct {

    }

    public class EntityBase : EntityBase<long>, INotifyPropertyChanged {

        /// <summary>
        /// Occurs when a property value changes.
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// Checks if a property already matches a desired value. Sets the property and
        /// notifies listeners only when necessary.
        /// </summary>
        /// <typeparam name="T">Type of the property.</typeparam>
        /// <param name="storage">Reference to a property with both getter and setter.</param>
        /// <param name="value">Desired value for the property.</param>
        /// <param name="propertyName">Name of the property used to notify listeners. This
        /// value is optional and can be provided automatically when invoked from compilers that
        /// support CallerMemberName.</param>
        /// <returns>True if the value was changed, false if the existing value matched the
        /// desired value.</returns>
        protected virtual bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null) {
            if (EqualityComparer<T>.Default.Equals(storage, value)) return false;

            storage = value;
            RaisePropertyChanged(propertyName);

            return true;
        }

        /// <summary>
        /// Checks if a property already matches a desired value. Sets the property and
        /// notifies listeners only when necessary.
        /// </summary>
        /// <typeparam name="T">Type of the property.</typeparam>
        /// <param name="storage">Reference to a property with both getter and setter.</param>
        /// <param name="value">Desired value for the property.</param>
        /// <param name="propertyName">Name of the property used to notify listeners. This
        /// value is optional and can be provided automatically when invoked from compilers that
        /// support CallerMemberName.</param>
        /// <param name="onChanged">Action that is called after the property value has been changed.</param>
        /// <returns>True if the value was changed, false if the existing value matched the
        /// desired value.</returns>
        protected virtual bool SetProperty<T>(ref T storage, T value, Action onChanged, [CallerMemberName] string propertyName = null) {
            if (EqualityComparer<T>.Default.Equals(storage, value)) return false;

            storage = value;
            onChanged?.Invoke();
            RaisePropertyChanged(propertyName);

            return true;
        }

        /// <summary>
        /// Raises this object's PropertyChanged event.
        /// </summary>
        /// <param name="propertyName">Name of the property used to notify listeners. This
        /// value is optional and can be provided automatically when invoked from compilers
        /// that support <see cref="CallerMemberNameAttribute"/>.</param>
        protected void RaisePropertyChanged([CallerMemberName] string propertyName = null) {
            OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
        }

        /// <summary>
        /// Raises this object's PropertyChanged event.
        /// </summary>
        /// <param name="args">The PropertyChangedEventArgs</param>
        protected virtual void OnPropertyChanged(PropertyChangedEventArgs args) {
            PropertyChanged?.Invoke(this, args);
        }
    }
}